#include <stdio.h>
#include "mxml.h"
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

mxml_node_t *getTopNodeFromString()
{
    std::string xml_str = "<?xml version=\"1.0\" encoding=\"GB2312\"?><Notify><CmdType>Keepalive</CmdType><SN>5765</SN><DeviceID>52010001111127999080</DeviceID><Status>OK</Status><Info></Info>\r\n</Notify>";
    mxml_node_t *xml = mxmlLoadString(NULL, xml_str.c_str(), MXML_NO_CALLBACK);
}

mxml_node_t *getTopNodeFromFile()
{
    FILE *fp = fopen("./src/Catalog.xml", "r");
    if (fp)
    {
        mxml_node_t *xml = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
        return xml;
    }
    return NULL;
}

void showTopNode(mxml_node_t *top)
{
    char temp[4096];
    memset(temp, 0, 4096);
    int size = mxmlSaveString(top, temp, 4096, MXML_NO_CALLBACK);
    printf("xml:%s", temp);
}

void printfElement(mxml_node_t *element)
{
    const char *text = mxmlGetText(element, NULL);
    if (text == NULL)
    {
        printf("[%p]value:empty\n", element);
    }
    else
    {
        printf("[%p]value:%s\n", element, text);
    }
}

void updateDeviceList(mxml_node_t *top)
{
    int count = 0;
    const char *platformID = mxmlGetText(mxmlFindPath(top, "Response/DeviceID"), NULL);
    const char *count_str = mxmlGetText(mxmlFindPath(top, "Response/SumNum"), NULL);
    if (count_str)
        count = atoi(count_str);
    if (platformID)
    {
        mxml_node_t *DeviceListNode = mxmlFindElement(top, top, "DeviceList", "Num", NULL, MXML_DESCEND);
        const char *list_count_str = mxmlElementGetAttr(DeviceListNode, "Num");
        if (list_count_str)
            count = atoi(count_str);
        mxml_node_t *ItemNode = mxmlFindElement(DeviceListNode, DeviceListNode, "Item", NULL, NULL, MXML_DESCEND);
        for (int i = 0; i < 1000; i++)
        {
            printf("[%d]start ItemNode:[%p]\n", i, ItemNode);
            if (ItemNode != NULL)
            {
                mxml_node_t *DeviceIDNode = mxmlFindElement(ItemNode, DeviceListNode, "DeviceID", NULL, NULL, MXML_DESCEND);
                printfElement(DeviceIDNode);
                mxml_node_t *NameNode = mxmlFindElement(ItemNode, DeviceListNode, "Name", NULL, NULL, MXML_DESCEND);
                printfElement(NameNode);
                mxml_node_t *ManufacturerNode = mxmlFindElement(ItemNode, DeviceListNode, "Manufacturer", NULL, NULL, MXML_DESCEND);
                printfElement(ManufacturerNode);
                mxml_node_t *ModelNode = mxmlFindElement(ItemNode, DeviceListNode, "Model", NULL, NULL, MXML_DESCEND);
                printfElement(ModelNode);
                mxml_node_t *OwnerNode = mxmlFindElement(ItemNode, DeviceListNode, "Owner", NULL, NULL, MXML_DESCEND);
                printfElement(OwnerNode);
                mxml_node_t *CivilCodeNode = mxmlFindElement(ItemNode, DeviceListNode, "CivilCode", NULL, NULL, MXML_DESCEND);
                printfElement(CivilCodeNode);
                mxml_node_t *AddressNode = mxmlFindElement(ItemNode, DeviceListNode, "Address", NULL, NULL, MXML_DESCEND);
                printfElement(AddressNode);
                mxml_node_t *ParentalNode = mxmlFindElement(ItemNode, DeviceListNode, "Parental", NULL, NULL, MXML_DESCEND);
                printfElement(ParentalNode);
                mxml_node_t *ParentIDNode = mxmlFindElement(ItemNode, DeviceListNode, "ParentID", NULL, NULL, MXML_DESCEND);
                printfElement(ParentIDNode);
                mxml_node_t *RegisterWayNode = mxmlFindElement(ItemNode, DeviceListNode, "RegisterWay", NULL, NULL, MXML_DESCEND);
                printfElement(RegisterWayNode);
                mxml_node_t *SecrecyNode = mxmlFindElement(ItemNode, DeviceListNode, "Secrecy", NULL, NULL, MXML_DESCEND);
                printfElement(SecrecyNode);
                mxml_node_t *StatusNode = mxmlFindElement(ItemNode, DeviceListNode, "Status", NULL, NULL, MXML_DESCEND);
                printfElement(StatusNode);
            }
            printf("[%d]start ItemNode:[%p]\n", i, ItemNode);
            ItemNode = mxmlGetNextSibling(ItemNode);
            ItemNode = mxmlGetNextSibling(ItemNode);
            if (ItemNode == NULL)
                break;
        }
    }
}

void updateDeviceList2(mxml_node_t *top)
{
    int count = 0;
    const char *platformID = mxmlGetText(mxmlFindPath(top, "Response/DeviceID"), NULL);
    const char *count_str = mxmlGetText(mxmlFindPath(top, "Response/SumNum"), NULL);
    if (count_str)
        count = atoi(count_str);
    if (platformID)
    {
        mxml_node_t *DeviceListNode = mxmlFindElement(top, top, "DeviceList", "Num", NULL, MXML_DESCEND);
        const char *list_count_str = mxmlElementGetAttr(DeviceListNode, "Num");
        if (list_count_str)
            count = atoi(count_str);
        // mxml_node_t *ItemNode = mxmlFindElement(DeviceListNode, DeviceListNode, "Item", NULL, NULL, MXML_DESCEND);
        for (mxml_node_t *ItemNode = mxmlFindElement(DeviceListNode, DeviceListNode, "Item", NULL, NULL, MXML_DESCEND); ItemNode != NULL; ItemNode = mxmlFindElement(ItemNode, DeviceListNode, "Item", NULL, NULL, MXML_DESCEND))
        {
            printf("start ItemNode:[%p]\n", ItemNode);
            mxml_node_t *DeviceIDNode = mxmlFindElement(ItemNode, DeviceListNode, "DeviceID", NULL, NULL, MXML_DESCEND);
            printfElement(DeviceIDNode);
            mxml_node_t *NameNode = mxmlFindElement(ItemNode, DeviceListNode, "Name", NULL, NULL, MXML_DESCEND);
            printfElement(NameNode);
            mxml_node_t *ManufacturerNode = mxmlFindElement(ItemNode, DeviceListNode, "Manufacturer", NULL, NULL, MXML_DESCEND);
            printfElement(ManufacturerNode);
            mxml_node_t *ModelNode = mxmlFindElement(ItemNode, DeviceListNode, "Model", NULL, NULL, MXML_DESCEND);
            printfElement(ModelNode);
            mxml_node_t *OwnerNode = mxmlFindElement(ItemNode, DeviceListNode, "Owner", NULL, NULL, MXML_DESCEND);
            printfElement(OwnerNode);
            mxml_node_t *CivilCodeNode = mxmlFindElement(ItemNode, DeviceListNode, "CivilCode", NULL, NULL, MXML_DESCEND);
            printfElement(CivilCodeNode);
            mxml_node_t *AddressNode = mxmlFindElement(ItemNode, DeviceListNode, "Address", NULL, NULL, MXML_DESCEND);
            printfElement(AddressNode);
            mxml_node_t *ParentalNode = mxmlFindElement(ItemNode, DeviceListNode, "Parental", NULL, NULL, MXML_DESCEND);
            printfElement(ParentalNode);
            mxml_node_t *ParentIDNode = mxmlFindElement(ItemNode, DeviceListNode, "ParentID", NULL, NULL, MXML_DESCEND);
            printfElement(ParentIDNode);
            mxml_node_t *RegisterWayNode = mxmlFindElement(ItemNode, DeviceListNode, "RegisterWay", NULL, NULL, MXML_DESCEND);
            printfElement(RegisterWayNode);
            mxml_node_t *SecrecyNode = mxmlFindElement(ItemNode, DeviceListNode, "Secrecy", NULL, NULL, MXML_DESCEND);
            printfElement(SecrecyNode);
            mxml_node_t *StatusNode = mxmlFindElement(ItemNode, DeviceListNode, "Status", NULL, NULL, MXML_DESCEND);
            printfElement(StatusNode);
            printf("end ItemNode:[%p]\n", ItemNode);
        }
    }
}

void test(mxml_node_t *top)
{
    mxml_node_t *node_Response = mxmlFindPath(top, "Response");
    if (node_Response)
    {
        printf("Response存在\n");
        mxml_node_t *DeviceIDNode = mxmlFindPath(top, "Response/DeviceID");
        // mxml_node_t *DeviceIDNode2 = mxmlFindElement(top, top, "DeviceID", NULL, NULL, MXML_DESCEND);
        mxml_node_t *SumNumNode = mxmlFindPath(top, "Response/SumNum");
        // mxml_node_t *SumNumNode2 = mxmlFindElement(top, top, "SumNum", NULL, NULL, MXML_DESCEND);
        // mxml_node_t *DeviceListNode = mxmlFindPath(top, "Response/DeviceList");
        mxml_node_t *DeviceListNode = mxmlFindElement(top, top, "DeviceList", "Num", NULL, MXML_DESCEND);
        if (DeviceIDNode != NULL && DeviceListNode != NULL || SumNumNode != NULL)
        {
            const char *platformID = mxmlGetText(DeviceIDNode, NULL);
            const char *count_str = NULL;
            if (DeviceListNode != NULL)
            {
                printf("Num\n");
                count_str = mxmlElementGetAttr(DeviceListNode, "Num");
            }
            if (count_str == NULL && SumNumNode != NULL)
            {
                printf("SumNumNode\n");
                count_str = mxmlGetText(SumNumNode, NULL);
            }
            int count = atoi(count_str);

            printf("-----------------------------------------垃圾库，早晚给换掉\n");

            for (mxml_node_t *node = mxmlGetFirstChild(DeviceListNode);
                 node != NULL;
                 node = mxmlGetNextSibling(node))
            {
                mxml_node_t *DeviceIDNode = mxmlFindElement(node, DeviceListNode, "DeviceID", NULL, NULL, MXML_DESCEND);
                printfElement(DeviceIDNode);
                mxml_node_t *NameNode = mxmlFindElement(node, DeviceListNode, "Name", NULL, NULL, MXML_DESCEND);
                printfElement(NameNode);
                mxml_node_t *ManufacturerNode = mxmlFindElement(node, DeviceListNode, "Manufacturer", NULL, NULL, MXML_DESCEND);
                printfElement(ManufacturerNode);
                mxml_node_t *ModelNode = mxmlFindElement(node, DeviceListNode, "Model", NULL, NULL, MXML_DESCEND);
                printfElement(ModelNode);
                mxml_node_t *OwnerNode = mxmlFindElement(node, DeviceListNode, "Owner", NULL, NULL, MXML_DESCEND);
                printfElement(OwnerNode);
                mxml_node_t *CivilCodeNode = mxmlFindElement(node, DeviceListNode, "CivilCode", NULL, NULL, MXML_DESCEND);
                printfElement(CivilCodeNode);
                mxml_node_t *AddressNode = mxmlFindElement(node, DeviceListNode, "Address", NULL, NULL, MXML_DESCEND);
                printfElement(AddressNode);
                mxml_node_t *ParentalNode = mxmlFindElement(node, DeviceListNode, "Parental", NULL, NULL, MXML_DESCEND);
                printfElement(ParentalNode);
                mxml_node_t *ParentIDNode = mxmlFindElement(node, DeviceListNode, "ParentID", NULL, NULL, MXML_DESCEND);
                printfElement(ParentIDNode);
                mxml_node_t *RegisterWayNode = mxmlFindElement(node, DeviceListNode, "RegisterWay", NULL, NULL, MXML_DESCEND);
                printfElement(RegisterWayNode);
                mxml_node_t *SecrecyNode = mxmlFindElement(node, DeviceListNode, "Secrecy", NULL, NULL, MXML_DESCEND);
                printfElement(SecrecyNode);
                mxml_node_t *StatusNode = mxmlFindElement(node, DeviceListNode, "Status", NULL, NULL, MXML_DESCEND);
                printfElement(StatusNode);
            }

            // mxml_node_t *ItemNode = mxmlFindPath(top, "Response/DeviceList/Item");
            mxml_node_t *ItemNode = mxmlFindElement(DeviceListNode, DeviceListNode, "Item", NULL, NULL, MXML_DESCEND);
            printf("-----------------------------------------\n");
            for (int i = 0; i < count; i++)
            {
                if (ItemNode != NULL)
                {
                    mxml_node_t *DeviceIDNode = mxmlFindElement(ItemNode, DeviceListNode, "DeviceID", NULL, NULL, MXML_DESCEND);
                    printfElement(DeviceIDNode);
                    mxml_node_t *NameNode = mxmlFindElement(ItemNode, DeviceListNode, "Name", NULL, NULL, MXML_DESCEND);
                    printfElement(NameNode);
                    mxml_node_t *ManufacturerNode = mxmlFindElement(ItemNode, DeviceListNode, "Manufacturer", NULL, NULL, MXML_DESCEND);
                    printfElement(ManufacturerNode);
                    mxml_node_t *ModelNode = mxmlFindElement(ItemNode, DeviceListNode, "Model", NULL, NULL, MXML_DESCEND);
                    printfElement(ModelNode);
                    mxml_node_t *OwnerNode = mxmlFindElement(ItemNode, DeviceListNode, "Owner", NULL, NULL, MXML_DESCEND);
                    printfElement(OwnerNode);
                    mxml_node_t *CivilCodeNode = mxmlFindElement(ItemNode, DeviceListNode, "CivilCode", NULL, NULL, MXML_DESCEND);
                    printfElement(CivilCodeNode);
                    mxml_node_t *AddressNode = mxmlFindElement(ItemNode, DeviceListNode, "Address", NULL, NULL, MXML_DESCEND);
                    printfElement(AddressNode);
                    mxml_node_t *ParentalNode = mxmlFindElement(ItemNode, DeviceListNode, "Parental", NULL, NULL, MXML_DESCEND);
                    printfElement(ParentalNode);
                    mxml_node_t *ParentIDNode = mxmlFindElement(ItemNode, DeviceListNode, "ParentID", NULL, NULL, MXML_DESCEND);
                    printfElement(ParentIDNode);
                    mxml_node_t *RegisterWayNode = mxmlFindElement(ItemNode, DeviceListNode, "RegisterWay", NULL, NULL, MXML_DESCEND);
                    printfElement(RegisterWayNode);
                    mxml_node_t *SecrecyNode = mxmlFindElement(ItemNode, DeviceListNode, "Secrecy", NULL, NULL, MXML_DESCEND);
                    printfElement(SecrecyNode);
                    mxml_node_t *StatusNode = mxmlFindElement(ItemNode, DeviceListNode, "Status", NULL, NULL, MXML_DESCEND);
                    printfElement(StatusNode);
                }
                ItemNode = mxmlGetNextSibling(ItemNode);
                if (ItemNode == NULL)
                    break;
            }
        }
        else
        {
            printf("缺少关键字段\n");
        }
    }
    else
    {
        printf("Response不存在\n");
    }
}

void textTest()
{
    std::string xml_str = "<?xml version=\"1.0\" encoding=\"GB2312\"?><Notify><CmdType>Keepalive</CmdType><SN>5765</SN><DeviceID>52010001111127999080</DeviceID><Status>OK</Status><Info></Info>\r\n</Notify>";
    mxml_node_t *xml = mxmlLoadString(NULL, xml_str.c_str(), MXML_NO_CALLBACK);

    mxml_node_t *e_DeviceID = mxmlFindElement(xml, xml, "DeviceID", NULL, NULL, MXML_DESCEND);

    mxml_type_t type = mxmlGetType(e_DeviceID);
    printf("type:%d\n", type);

    auto text = mxmlGetText(e_DeviceID, NULL);
    printf("%s\n", text);

    int temp = 1;
    auto text1 = mxmlGetText(e_DeviceID, &temp);
    printf("%s\n", text1);

    // auto opaque = mxmlGetOpaque(e_DeviceID);
    // printf("%s\n", opaque);

    std::string textValue = "";
    for (mxml_node_t *child = mxmlGetFirstChild(e_DeviceID); child != nullptr; child = mxmlGetNextSibling(child))
    {
        auto text = mxmlGetText(child, NULL);
        if (!textValue.empty() && strlen(text) != 0)
        {
            textValue += " ";
        }
        if (text != nullptr)
        {
            textValue += std::string(text);
        }
    }
    printf(">>>%s<<<\n", textValue.c_str());
}

int main(int argn, char **argv)
{
    mxml_node_t *top = getTopNodeFromFile();
    if (top)
    {
        // printf("-------------------------------------------------------------\n");
        // showTopNode(top);
        // printf("-------------------------------------------------------------\n");
        // updateDeviceList2(top);
        // printf("-------------------------------------------------------------\n");
        // updateDeviceList(top);
        printf("-------------------------------------------------------------\n");
        textTest(); // TEXT元素中文本有空格
        printf("-------------------------------------------------------------\n");
        // test(top);
        // printf("-------------------------------------------------------------\n");
        return 0;
    }
    else
    {
        printf("xml解析失败\n");
    }
    return 0;
}